package com.tau.egonetwork.gui.core;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;

import com.tau.egonetwork.profiles.Profile;

public class EgoNetworkComboBox<T extends Comparable<T>> extends Composite {

	private Combo comboBox;
	
	private ArrayList<Profile<T>> datasource;
	private HashMap<Integer, Integer> suggestions = new HashMap<Integer, Integer>();
	
	boolean suggestionsON = false;

	public EgoNetworkComboBox(Composite parent, int style) {
		super(parent, style);
		
		//define layout and remove margins:
		GridLayout layout = new GridLayout(1, true);
		layout.marginWidth = 0;
		layout.marginLeft = 0;
		layout.marginRight = 0;
		setLayout(layout);
		
		//fill composite with combo:
		comboBox = new Combo(this, style);
		comboBox.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		
		comboBox.setTextLimit(50);
		
		//set Listener:
		comboBox.addListener(SWT.KeyUp, textModifiedListener);
		comboBox.addListener(SWT.FocusIn, focusInListener);
	}
	
	public void setDatasource(ArrayList<Profile<T>> objects) {
		datasource = objects;
		populateCombo();
	}
	
	private void populateCombo() {
		
		if (datasource == null)
			return;
		
		comboBox.removeAll();
		
		if (suggestionsON) {
			Collection<Integer> values = suggestions.values();
			for (int v : values) {
				comboBox.add(datasource.get(v).getName());
			}
		} else {
			for (Profile<?> p : datasource) {
				comboBox.add(p.getName());
			}
		}
	}
	
	Listener textModifiedListener = new Listener() {
		
		@Override
		public void handleEvent(Event e) {
			
			if (e.keyCode == SWT.ARROW_DOWN) {
				if (comboBox.getItemCount() > 0)
					comboBox.setListVisible(true);
				return;
			}
			
			//ignore all other arrow keys (maybe user just want to go back in text using keyboard):
			if (e.keyCode == SWT.ARROW_LEFT || e.keyCode == SWT.ARROW_RIGHT) {
				return;
			}
						
			String searchText = comboBox.getText();
			suggestions.clear();
			
			if (searchText == null || searchText.trim().equals("")) {
				suggestionsON = false;
				populateCombo();
				return;
			}
			
			suggestionsON = true;
			comboBox.removeAll();
			
			int newComboIndex = 0;
			
			for (int i = 0; i < datasource.size(); i++) {
				if (datasource.get(i).getName().toLowerCase().startsWith(searchText.toLowerCase().trim())) {
					comboBox.add(datasource.get(i).getName());
					suggestions.put(newComboIndex++, i);
				}
			}
			
			comboBox.setText(searchText);
			comboBox.setSelection(new Point(searchText.length(), searchText.length()));
			comboBox.setFocus();
		}
	};
		
	Listener focusInListener = new Listener() {

		@Override
		public void handleEvent(Event event) {
			int len = comboBox.getText().length();
			if (len > 0)
				comboBox.setSelection(new Point(len, len));
		}
		
	};
	
	public void refresh() {
		if (comboBox.getText().length() > 0) {
			suggestionsON = false;
			suggestions.clear();
		}
		populateCombo();
	}
	
	public int getSelectionIndex() {
		
		if (suggestionsON) {
			if (comboBox.getSelectionIndex() == -1)
				return -1;
			return suggestions.get(comboBox.getSelectionIndex());
		}
		
		return comboBox.getSelectionIndex();
	}
	
	public void remove(int index) {
		datasource.remove(index);		
		suggestionsON = false;
		suggestions.clear();
		populateCombo();
	}

}
